package cuiyt.juc.abstractqueuedsynchronizer;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author cyt
 * @describe
 * @create 2021-01-06 19:48
 */
public class ConditionTest {
    private static Lock reentrantLock = new ReentrantLock(true);
    Condition condition = reentrantLock.newCondition();

    public void createOrder() throws InterruptedException {
        Thread.State state = Thread.currentThread().getState();
        reentrantLock.lock();
        // 比如我们同一时间，只允许一个线程创建订单
        // 通常，lock 之后紧跟着 try 语句
        try {
            condition.wait();
            TimeUnit.SECONDS.sleep(2);
            // 这块代码同一时间只能有一个线程进来(获取到锁的线程)，
            // 其他的线程在lock()方法上阻塞，等待获取到锁，再进来
            // 执行代码...
            // 执行代码...
            // 执行代码...
            System.out.println(Thread.currentThread().getName() + "的状态是 - >  " + state + "在创建订单");
            condition.signal();
            deleteOrder();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 释放锁
            reentrantLock.unlock();
        }
    }

    public void deleteOrder() throws InterruptedException {
        Thread.State state = Thread.currentThread().getState();
        // 比如我们同一时间，只允许一个线程创建订单
        condition.wait();
        // 通常，lock 之后紧跟着 try 语句
        try {
            System.out.println(Thread.currentThread().getName() + "的状态是 - >  " + state + "在删除订单");
            // 这块代码同一时间只能有一个线程进来(获取到锁的线程)，
            // 其他的线程在lock()方法上阻塞，等待获取到锁，再进来
            // 执行代码...
            // 执行代码...
            // 执行代码...
        } finally {
            // 释放锁
            condition.signal();
        }
    }

    public static void main(String[] args) {
        AbstractQueuedSynchronizerTest test = new AbstractQueuedSynchronizerTest();
        test.createOrder();
        /* test.deleteOrder()*/
        ;
        new Thread(() -> {
            test.createOrder();
        }, "A").start();

        new Thread(() -> {
            test.createOrder();
        }, "B").start();
    }
}
